package com.gao.api.gate.quick.core.async;

import com.gao.api.gate.quick.core.registry.Registry;
import com.gao.api.gate.quick.core.registry.RegistryEvent;
import com.gao.api.gate.quick.core.registry.ThreadSafeSimpleRegistry;

import java.util.Collection;
import java.util.LinkedList;

/**
 * <p></p>
 *
 * @author gaoshuangwen
 * @since 2022/01/12 13:04
 */
public class ListenableFutureListenerRegistry<T> extends ThreadSafeSimpleRegistry<Listener<T>> implements Registry<Listener<T>> {

    private Object result;

    private State state = State.NEW;

    public ListenableFutureListenerRegistry() {
        super(new LinkedList<>());
    }
    @Override
    @SuppressWarnings("unchecked")
    public void onChanged(RegistryEvent event) {
        // 只关注新增的情况
        if(event != null && event.equals(RegistryEvent.add)){
            switch (this.state){
                case NEW:
                    break;
                case SUCCESS:
                    success((T) this.result);
                    break;
                case FAILURE:
                    failure((Throwable) this.result);
                    break;
            }
        }

    }

    public synchronized void success(T result) {
        this.state = State.SUCCESS;
        this.result = result;
        Collection<Listener<T>> nodes = getNodes();
        nodes.forEach(listener -> {
            notify(listener,true);
        });

    }
    public synchronized void failure(Throwable ex) {
        this.state = State.FAILURE;
        this.result = ex;
        Collection<Listener<T>> nodes = getNodes();
        nodes.forEach(listener -> {
            notify(listener,false);
        });
    }
    @SuppressWarnings("unchecked")
    private void notify(Listener<T> listener,boolean success) {
        try {
            if(success){
                listener.onSuccess((T) this.result);
            }else {
                listener.onFailure((Throwable) this.result);
            }
        }
        catch (Throwable ex) {
            // Ignore
        }
    }


    private enum State {NEW, SUCCESS, FAILURE}
}
